﻿using System;

namespace Net.Entities
{
    public class Object : IDisposable
    {
        internal bool _disposed;

        public string Name { get; set; }
        public bool IsDisposed => _disposed;

        public static Object Instantiate(Object original, Vector3 position, Quaternion rotation)
        {
            throw new NotImplementedException();
        }

        public static Object Instantiate(Object original, Vector3 position, Quaternion rotation, Transform parent)
        {
            throw new NotImplementedException();
        }

        public static Object Instantiate(Object original)
        {
            throw new NotImplementedException();
        }

        public static Object Instantiate(Object original, Transform parent)
        {
            return Instantiate(original, parent, false);
        }

        public static Object Instantiate(Object original, Transform parent, bool instantiateInWorldSpace)
        {
            throw new NotImplementedException();
        }

        public static T Instantiate<T>(T original) where T : Object
        {
            throw new NotImplementedException();
        }

        public static T Instantiate<T>(T original, Vector3 position, Quaternion rotation) where T : Object
        {
            return (T)((object)Instantiate(original, position, rotation));
        }

        public static T Instantiate<T>(T original, Vector3 position, Quaternion rotation, Transform parent) where T : Object
        {
            return (T)((object)Instantiate(original, position, rotation, parent));
        }

        public static T Instantiate<T>(T original, Transform parent) where T : Object
        {
            return Instantiate<T>(original, parent, false);
        }

        public static T Instantiate<T>(T original, Transform parent, bool worldPositionStays) where T : Object
        {
            return (T)((object)Instantiate(original, parent, worldPositionStays));
        }

        public virtual void Destroy(float time)
        {
        }

        public void Destroy()
        {
            Destroy(0f);
        }

        public void DestroyImmediate()
        {
            Dispose();
        }

        public static Object[] FindObjectsOfType(Type type)
        {
            return FindObjectsOfType(type, false);
        }

        public static Object[] FindObjectsOfType(Type type, bool includeInactive)
        {
            throw new NotImplementedException();
        }

        public static Object[] FindObjectsByType(Type type, FindObjectsSortMode sortMode)
        {
            return FindObjectsByType(type, FindObjectsInactive.Exclude, sortMode);
        }

        public static Object[] FindObjectsByType(Type type, FindObjectsInactive findObjectsInactive, FindObjectsSortMode sortMode)
        {
            throw new NotImplementedException();
        }

        public static void DontDestroyOnLoad([NotNull("NullExceptionObject")] Object target)
        {
            throw new NotImplementedException();
        }

        public static Object[] FindSceneObjectsOfType(Type type)
        {
            return FindObjectsOfType(type);
        }

        public static Object[] FindObjectsOfTypeIncludingAssets(Type type)
        {
            throw new NotImplementedException();
        }

        public static T[] FindObjectsOfType<T>() where T : Object
        {
            return Resources.ConvertObjects<T>(FindObjectsOfType(typeof(T), false));
        }

        public static T[] FindObjectsByType<T>(FindObjectsSortMode sortMode) where T : Object
        {
            return Resources.ConvertObjects<T>(FindObjectsByType(typeof(T), FindObjectsInactive.Exclude, sortMode));
        }

        public static T[] FindObjectsOfType<T>(bool includeInactive) where T : Object
        {
            return Resources.ConvertObjects<T>(FindObjectsOfType(typeof(T), includeInactive));
        }

        public static T[] FindObjectsByType<T>(FindObjectsInactive findObjectsInactive, FindObjectsSortMode sortMode) where T : Object
        {
            return Resources.ConvertObjects<T>(FindObjectsByType(typeof(T), findObjectsInactive, sortMode));
        }

        public static T FindObjectOfType<T>() where T : Object
        {
            return (T)((object)FindObjectOfType(typeof(T), false));
        }

        public static T FindObjectOfType<T>(bool includeInactive) where T : Object
        {
            return (T)((object)FindObjectOfType(typeof(T), includeInactive));
        }

        public static T FindFirstObjectByType<T>() where T : Object
        {
            return (T)((object)FindFirstObjectByType(typeof(T), FindObjectsInactive.Exclude));
        }

        public static T FindAnyObjectByType<T>() where T : Object
        {
            return (T)((object)FindAnyObjectByType(typeof(T), FindObjectsInactive.Exclude));
        }

        public static T FindFirstObjectByType<T>(FindObjectsInactive findObjectsInactive) where T : Object
        {
            return (T)((object)FindFirstObjectByType(typeof(T), findObjectsInactive));
        }

        public static T FindAnyObjectByType<T>(FindObjectsInactive findObjectsInactive) where T : Object
        {
            return (T)((object)FindAnyObjectByType(typeof(T), findObjectsInactive));
        }

        public static Object[] FindObjectsOfTypeAll(Type type)
        {
            return Resources.FindObjectsOfTypeAll(type);
        }

        public static Object FindObjectOfType(Type type)
        {
            Object[] array = FindObjectsOfType(type, false);
            bool flag = array.Length != 0;
            Object result;
            if (flag)
            {
                result = array[0];
            }
            else
            {
                result = null;
            }
            return result;
        }

        public static Object FindFirstObjectByType(Type type)
        {
            Object[] array = FindObjectsByType(type, FindObjectsInactive.Exclude, FindObjectsSortMode.InstanceID);
            return (array.Length != 0) ? array[0] : null;
        }

        public static Object FindAnyObjectByType(Type type)
        {
            Object[] array = FindObjectsByType(type, FindObjectsInactive.Exclude, FindObjectsSortMode.None);
            return (array.Length != 0) ? array[0] : null;
        }

        public static Object FindObjectOfType(Type type, bool includeInactive)
        {
            Object[] array = FindObjectsOfType(type, includeInactive);
            bool flag = array.Length != 0;
            Object result;
            if (flag)
            {
                result = array[0];
            }
            else
            {
                result = null;
            }
            return result;
        }

        public static Object FindFirstObjectByType(Type type, FindObjectsInactive findObjectsInactive)
        {
            Object[] array = FindObjectsByType(type, findObjectsInactive, FindObjectsSortMode.InstanceID);
            return (array.Length != 0) ? array[0] : null;
        }

        public static Object FindAnyObjectByType(Type type, FindObjectsInactive findObjectsInactive)
        {
            Object[] array = FindObjectsByType(type, findObjectsInactive, FindObjectsSortMode.None);
            return (array.Length != 0) ? array[0] : null;
        }

        public virtual void Dispose() => _disposed = true;

        public static bool operator ==(Object left, Object right)
        {
            if (left is null && right is null) // ActorBase a = null; if(a == null) 或 if(null == a) 处理
                return true;
            if (right is null)
                return left._disposed;
            if (left is null)
                return right._disposed;
            return ReferenceEquals(left, right);
        }

        public static bool operator !=(Object left, Object right) => !(left == right);

        public override string ToString()
        {
            return $"{Name} ({GetType()})";
        }
    }
}